//---------------------------------------------------------------------------------
// Copyright (c) 2008 VoiceLynx Project
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
//     1. The origin of this software must not be misrepresented; you must not
//        claim that you wrote the original software. If you use this software
//        in a product, an acknowledgment in the product documentation would be
//        appreciated but is not required.
//
//     2. Altered source versions must be plainly marked as such, and must not be
//        misrepresented as being the original software.
//
//     3. This notice may not be removed or altered from any source
//        distribution.
//---------------------------------------------------------------------------------

#ifndef __VLPrerequisites_h__
#define __VLPrerequisites_h__


#include "wx/wxprec.h"

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

#define VL_WINDOWS_H_DEFINED (1)

#include <vector>
#include <map>
#include <iostream>
#include <cassert>

// TODO: One day, we will have a #include "VoiceLynx.h" that disables this warning, includes
// everything, then enables it - or we'll have a head.h and foot.h on all cpp's to prevent
// the warning from showing - or we'll remove the source of these warnings
#pragma warning (disable: 4100) // unreferenced formal parameter

// the application icon (under Windows and OS/2 it is in resources and even
// though we could still include the XPM here it would be unused)
#if !defined(__WXMSW__) && !defined(__WXPM__)
#include "../sample.xpm"
#endif

#define VL_DEFAULT_PORT (17899)

// Numerical primitives
typedef char           VL8;
typedef unsigned char  VLU8;
typedef short          VL16;
typedef unsigned short VLU16;
typedef int            VL32;
typedef unsigned int   VLU32;
typedef long           VL64;
typedef unsigned long  VLU64;

typedef float          VLF32;
typedef double         VLF64;

typedef bool           VLBool;

typedef std::string    VLString;

// TODO: Make this a class in its own file, use aggregation instead of inheritance of the vector
template <class T>
class VLPtrList : public std::vector<T*>
{
public:
  virtual ~VLPtrList()
  {
    for (std::vector<T*>::iterator iter = this->begin(); 
      iter != this->end(); ++iter)
    {
      delete *iter;
    }
  }
};

// Bytes, byte arrays
typedef VLU8                       VLByte;
typedef std::vector<VLByte>        VLByteArray;
typedef std::auto_ptr<VLByteArray> VLByteArrayPtr;
typedef VLPtrList<VLByteArray>    VLByteArrayPtrList;

#define VL_ASSERT(X) assert(X)
#define VL_ASSERT_ALWAYS() VL_ASSERT(0)

namespace static_assert
{
  template <bool> struct STATIC_ASSERT_FAILURE;
  template <> struct STATIC_ASSERT_FAILURE<true> { enum { value = 1 }; };

  template<int x> struct static_assert_test{};
}

#define VL_COMPILER_ASSERT(x) \
  typedef ::static_assert::static_assert_test<\
  sizeof(::static_assert::STATIC_ASSERT_FAILURE< (bool)( x ) >)>\
  _static_assert_typedef##__LINE__

#define VL_INIT_DEBUG_CONSOLE()               \
  AllocConsole();                             \
  FILE* f;                                    \
  freopen_s(&f, "conout$", "w", stdout);      \
  freopen_s(&f, "conout$", "w", stderr);      \
  freopen_s(&f, "conin$", "r", stdin)

#define VL_TRACE(str)                         \
  {                                           \
    std::cout << str << std::endl;            \
  }

#define VL_DECLARE_CUSTOM_EXCEPTION_TYPE(_TypeName)                      \
    class _TypeName : public std::exception                              \
    {                                                                    \
    public:                                                              \
      _TypeName(std::string m) : msg(m) {}                               \
      virtual ~_TypeName() throw() {}                                    \
                                                                         \
      const char* what() const throw() { return msg.c_str(); }           \
                                                                         \
    private:                                                             \
      std::string msg;                                                   \
    };


#define VL_THROW0(_ExceptionType)                 throw _ExceptionType;
#define VL_THROW1(_ExceptionType, _Arg0)          throw _ExceptionType(_Arg0)
#define VL_THROW2(_ExceptionType, _Arg0, _Arg1)   throw _ExceptionType(_Arg0, _Arg1)



#endif
